\defmodule{ListOfStatProbes}

Represents a list of statistical probes that
can be managed simultaneously.
Each element of this list is a \externalclass{umontreal.iro.lecuyer.stat}{StatProbe}
instance which can be obtained and manipulated.

When constructing a list of statistical probes, one specifies the
concrete subclass of the \class{StatProbe} objects in it.
One then creates an empty list of probes, and fills
it with statistical probes.
If the list is not intended to be modified, one can then use the
\method{setUnmodifiable}{} to prevent any change in the contents of
the list.

Each list of statistical probes can have a global name describing
the contents of its elements, and local names associated with each
individual probe.  For example, a list of statistical probes for
the waiting times can have the global name \texttt{Waiting times}
while the individual probes have local names \texttt{type 1},
\texttt{type 2}, etc.  These names are used for formatting reports.

Facilities are provided to fill arrays with sums, averages, etc.\ obtained
from the individual statistical probes.
Methods are also provided to manipulate the contents of the list.
However, one should always call \texttt{init} immediately after adding or
removing statistical probes in the list.

\bigskip\hrule

\begin{code}
\begin{hide}
/*
 * Class:        ListOfStatProbes
 * Description:  List of statistical probes
 * Environment:  Java
 * Software:     SSJ 
 * Copyright (C) 2001  Pierre L'Ecuyer and Universite de Montreal
 * Organization: DIRO, Universite de Montreal
 * @author       Éric Buist 
 * @since        2007

 * SSJ is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License (GPL) as published by the
 * Free Software Foundation, either version 3 of the License, or
 * any later version.

 * SSJ is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * A copy of the GNU General Public License is available at
   <a href="http://www.gnu.org/licenses">GPL licence site</a>.
 */
\end{hide}
package umontreal.iro.lecuyer.stat.list;\begin{hide}

import umontreal.iro.lecuyer.util.PrintfFormat;
import java.util.List;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.RandomAccess;
import umontreal.iro.lecuyer.stat.StatProbe;
\end{hide}


public class ListOfStatProbes<E extends StatProbe>
                                implements Cloneable, List<E>, RandomAccess\begin{hide} {

   // probes must implement RandomAccess, otherwise this class must not implement RandomAccess.
   private List<E> probes;
   private List<ArrayOfObservationListener> listeners = new ArrayList<ArrayOfObservationListener>();
   protected boolean collect = true;
   protected boolean broadcast = false;
   protected String name;\end{hide}
\end{code}
\subsubsection*{Constructors}
\begin{code}

   public ListOfStatProbes()\begin{hide} {
      probes = new ArrayList<E>();
   }\end{hide}
\end{code}
\begin{tabb}   Constructs an empty list of statistical probes.
\end{tabb}
\begin{code}

   public ListOfStatProbes (String name)\begin{hide} {
      probes = new ArrayList<E>();
      this.name = name;
   }\end{hide}
\end{code}
\begin{tabb}   Constructs an empty list of statistical probes with
  name \texttt{name}.
\end{tabb}
\begin{htmlonly}
   \param{name}{the name of the new list.}
\end{htmlonly}
\subsubsection*{Methods}
\begin{code}

   public String getName()\begin{hide} {
      return name;
   }\end{hide}
\end{code}
\begin{tabb}   Returns the global name of this list of statistical probes.
\end{tabb}
\begin{htmlonly}
   \return{the global name of the list.}
\end{htmlonly}
\begin{code}

   public void setName (String name)\begin{hide} {
      this.name = name;
   }\end{hide}
\end{code}
\begin{tabb}   Sets the global name of this list to \texttt{name}.
\end{tabb}
\begin{htmlonly}
   \param{name}{the new global name of the list.}
\end{htmlonly}
\begin{code}

   public boolean isModifiable()\begin{hide} {
      return probes instanceof ArrayList;
   }\end{hide}
\end{code}
\begin{tabb}   Determines if this list of statistical probes is
  modifiable, i.e., if probes can be added or removed.
  Any list of statistical probes is modifiable by default, until one calls the
  \method{setUnmodifiable}{} method.
\end{tabb}
\begin{code}

   public void setUnmodifiable()\begin{hide} {
      if (isModifiable())
         probes = Collections.unmodifiableList (probes);
   }\end{hide}
\end{code}
\begin{tabb}  Forbids any future modification to this list of
  statistical probes.
  After this method is called, any attempt to modify the list results
  in an exception.
   Setting a list unmodifiable can be useful if some data structures
   are defined depending on the probes in the list.
\end{tabb}
\begin{code}

   public void init()\begin{hide} {
      for (StatProbe probe : probes) {
         if (probe != null)
            probe.init();
      }
   }\end{hide}
\end{code}
\begin{tabb}   Initializes this list of statistical probes by calling
 \externalmethod{umontreal.iro.lecuyer.stat}{StatProbe}{init}{()} on each element.
\end{tabb}
\begin{code}

   public void sum (double[] s)\begin{hide} {
      if (s.length != size())
         throw new IllegalArgumentException
            ("Invalid length of the given array: given length is " + s.length +
             ", required length is " + size());
      int i = 0;
      for (StatProbe probe : probes)
         s[i++] = probe == null ? Double.NaN : probe.sum();
   }\end{hide}
\end{code}
\begin{tabb}   For each probe in the list, computes
 the sum by calling \externalmethod{umontreal.iro.lecuyer.stat}{StatProbe}{sum}{()}, and stores
 the results into the array \texttt{s}. This method throws an exception if the size of \texttt{s}
 mismatches with the size of the list.
\end{tabb}
\begin{htmlonly}
   \param{s}{the array to be filled with sums.}
   \exception{NullPointerException}{if \texttt{s} is \texttt{null}.}
   \exception{IllegalArgumentException}{if \texttt{s.length}
    does not correspond to \method{size}{()}.}
\end{htmlonly}
\begin{code}

   public void average (double[] a)\begin{hide} {
      if (a.length != size())
         throw new IllegalArgumentException
            ("Invalid length of the given array: given length is " + a.length +
             ", required length is " + size());
      int i = 0;
      for (StatProbe probe : probes)
         a[i++] = probe == null ? Double.NaN : probe.average();
   }\end{hide}
\end{code}
\begin{tabb}   For each probe in this list, computes
 the average by calling \externalmethod{umontreal.iro.lecuyer.stat}{StatProbe}{average}{()}, and stores
 the results into the array \texttt{a}. This method throws an exception if the size of \texttt{s}
 mismatches with the size of the list.
\end{tabb}
\begin{htmlonly}
   \param{a}{the array to be filled with averages.}
   \exception{NullPointerException}{if \texttt{a} is \texttt{null}.}
   \exception{IllegalArgumentException}{if \texttt{a.length}
    does not correspond to \method{size}{()}.}
\end{htmlonly}
\begin{code}

   public boolean isCollecting()\begin{hide} {
      return collect;
   }\end{hide}
\end{code}
\begin{tabb}   Determines if this list of statistical probes
 is collecting values. Each probe of the list could or could not
 be collecting values. The default is \texttt{true}.
\end{tabb}
\begin{htmlonly}
   \return{the status of statistical collecting.}
\end{htmlonly}
\begin{code}

   public void setCollecting (boolean c)\begin{hide} {
      collect = c;
   }\end{hide}
\end{code}
\begin{tabb}   Sets the status of the statistical collecting
 mechanism to \texttt{c}.  A \texttt{true} value
 turns statistical collecting ON, a \texttt{false}
 value turns it OFF.
\end{tabb}
\begin{htmlonly}
   \param{c}{the status of statistical collecting.}
\end{htmlonly}
\begin{code}

   public boolean isBroadcasting()\begin{hide} {
      return broadcast;
   }\end{hide}
\end{code}
\begin{tabb}   Determines if this list of statistical probes
 is broadcasting observations to registered observers.
 The default is \texttt{false}.
\end{tabb}
\begin{htmlonly}
   \return{the status of broadcasting.}
\end{htmlonly}
\begin{code}

   public void setBroadcasting (boolean b)\begin{hide} {
      broadcast = b;
   }\end{hide}
\end{code}
\begin{tabb}   Sets the status of the observation broadcasting
 mechanism to \texttt{b}.  A \texttt{true} value
 turns broadcasting ON, a \texttt{false}
 value turns it OFF.
\end{tabb}
\begin{htmlonly}
   \param{b}{the status of broadcasting.}
\end{htmlonly}
\begin{code}

   public void addArrayOfObservationListener (ArrayOfObservationListener l)\begin{hide} {
      if (l == null)
         throw new NullPointerException();
      if (!listeners.contains (l))
         listeners.add (l);
   }\end{hide}
\end{code}
\begin{tabb}   Adds the observation listener \texttt{l} to the list of observers of
    this list of statistical probes.
\end{tabb}
\begin{htmlonly}
   \param{l}{the new observation listener.}
   \exception{NullPointerException}{if \texttt{l} is \texttt{null}.}
\end{htmlonly}
\begin{code}

   public void removeArrayOfObservationListener (ArrayOfObservationListener l)\begin{hide} {
      listeners.remove (l);
   }\end{hide}
\end{code}
\begin{tabb}   Removes the observation listener \texttt{l} from the list of observers of
    this list of statistical probes.
\end{tabb}
\begin{htmlonly}
   \param{l}{the observation listener to be deleted.}
\end{htmlonly}
\begin{code}

   public void clearArrayOfObservationListeners()\begin{hide} {
      listeners.clear();
   }\end{hide}
\end{code}
\begin{tabb}   Removes all observation listeners from the list of observers of
    this list of statistical probes.
\end{tabb}
\begin{code}

   public void notifyListeners (double[] x)\begin{hide} {
      if (!broadcast)
         return;
      // We could also use the enhanced for loop here, but this is less efficient.
      final int nl = listeners.size();
      for (int i = 0; i < nl; i++)
         listeners.get (i).newArrayOfObservations (this, x);
   }\end{hide}
\end{code}
\begin{tabb}   Notifies the observation \texttt{x} to all registered observers
   if broadcasting is ON.  Otherwise, does nothing.
\end{tabb}
\begin{code}

   public String report()\begin{hide} {
      return StatProbe.report (name, this);
   }\end{hide}
\end{code}
\begin{tabb}   Formats a report for each probe in the list of
 statistical probes.  The returned string is constructed by
 using \texttt{StatProbe.report (getName(), this)}.
\end{tabb}
\begin{htmlonly}
   \return{the report formatted as a string.}
\end{htmlonly}
\begin{code}

   public ListOfStatProbes<E> clone()\begin{hide} {
      ListOfStatProbes<E> sa;
      try {
         sa = (ListOfStatProbes<E>)super.clone();
      }
      catch (CloneNotSupportedException cne) {
         throw new IllegalStateException ("CloneNotSupportedException for a class implementing Cloneable");
      }
      if (probes != null)
         sa.probes = new ArrayList<E> (probes);
      return sa;
   }\end{hide}
\end{code}
\begin{tabb}   Clones this object.   This makes a shallow copy
  of this list, i.e., this does not clone all the probes in the list.
  The created clone is modifiable, even if the original list is unmodifiable.
\end{tabb}
\begin{code}
\begin{hide}

   public boolean add (E o) {
      return probes.add (o);
   }

   public void add (int index, E o) {
      probes.add (index, o);
   }

   public boolean addAll (Collection<? extends E> c) {
      return probes.addAll (c);
   }

   public boolean addAll (int index, Collection<? extends E> c) {
      return probes.addAll (index, c);
   }

   public void clear() {
      probes.clear();
   }

   public boolean contains (Object o) {
      return probes.contains (o);
   }

   public boolean containsAll (Collection<?> c) {
      return probes.containsAll (c);
   }

   public boolean equals (Object o) {
      return probes.equals (o);
   }

   public E get (int index) {
      return probes.get (index);
   }

   public int hashCode() {
      return probes.hashCode();
   }

   public int indexOf (Object o) {
      return probes.indexOf (o);
   }

   public boolean isEmpty() {
      return probes.isEmpty();
   }

   public Iterator<E> iterator() {
      return probes.iterator();
   }

   public int lastIndexOf (Object o) {
      return probes.lastIndexOf (o);
   }

   public ListIterator<E> listIterator() {
      return probes.listIterator();
   }

   public ListIterator<E> listIterator (int index) {
      return probes.listIterator();
   }

   public E remove (int index) {
      return probes.remove (index);
   }

   public boolean remove (Object o) {
      return probes.remove (o);
   }

   public boolean removeAll (Collection<?> c) {
      return probes.removeAll (c);
   }

   public boolean retainAll (Collection<?> c) {
      return probes.retainAll (c);
   }

   public E set (int index, E element) {
      return probes.set (index, element);
   }

   public int size() {
      return probes.size();
   }

   public List<E> subList (int fromIndex, int toIndex) {
      return probes.subList (fromIndex, toIndex);
   }

   public Object[] toArray() {
      return probes.toArray();
   }

   public <T> T[] toArray (T[] a) {
      return probes.toArray (a);
   }

\end{hide}
\end{code}
\begin{code}\begin{hide}
}\end{hide}
\end{code}

